//
//  HLMessageSessionViewController.m
//  YueYue
//
//  Created by hulu001 on 2023/6/12.
//

#import "HLMessageSessionViewController.h"
#import "HLUserDetailViewController.h"
#import "HLReportViewController.h"
#import "HLMessageSessionSettingViewController.h"
#import "HLSessionConfig.h"
#import "HLMessageMaker.h"
#import <NIMSDK/NIMSDK.h>
#import <AVFoundation/AVFoundation.h>
#import <iflyMSC/iflyMSC.h>
#import "IATConfig.h"
#import "ISRDataHelper.h"

#import "HLUserInfoRequest.h"
#import "HLUserOptionRequest.h"
#import "HLAudioView.h"
#import "XKLIMVoiceConverter.h"
#import "HLTransModel.h"
#import "HLSessionUntils.h"
#import "HLIMKitInputViewImpl.h"
#import "HLIMInputBar.h"
#import "HLIMKitTitleView.h"
#import "HLMenuView.h"
#import "HLSpeakerView.h"
#import "HLPickerManager.h"
#import "HLGiftContainerView.h"
#import "HLPreviewGiftView.h"
#import "HLPhotosWallView.h"

#import "HLAccostAttachment.h"
#import "HLGiftAttachment.h"
#import "HLPushAttachment.h"
#import "HLOtherRemidAttach.h"
#import "HLVideoGuideAttachment.h"
#import "HLPayRemindAttachment.h"

// 翻译
#import "YMTranslacteRequest.h"
#import "NSString+GPRegex.h"
#import "GPLangCache.h"
#import "YMSessionRequest.h"

@interface HLMessageSessionViewController ()<IFlySpeechRecognizerDelegate>
{
    BOOL _inMicroPermission; // 正在麦克风授权
    int _availableSendCount;// 可用发消息次数
    BOOL _isNeedShowFeeTip; // 是否显示收费提示
}
@property (nonatomic, strong) id<HLIMSessionConfig> config;
@property (nonatomic, strong) IFlySpeechRecognizer *iFlySpeechRecognizer;//Recognition conrol without view
@property (nonatomic, strong) IFlyPcmRecorder *pcmRecorder;
// 正在转文字的语音消息
@property (nonatomic, strong) NIMMessage *translatingMessage;
// 翻译文字中
@property (nonatomic, assign) BOOL needTransLanguage;
@property (nonatomic, copy)   NSString *iflyResult;
@property (nonatomic, strong) NIMMessage *quoteMessage;
@property (nonatomic, strong) HLPhotosWallView *photosWallView;

@property (nonatomic,   assign) BOOL realVoice;
@property (nonatomic,   strong) NSArray<HLTransModel *> *realTransModels;
@property (nonatomic,   assign) NSInteger currentRealVoiceTransIndex;// 当前实时翻译模式的索引，从transModels中查找

@property (nonatomic, copy) NSString *audioPath;// 录音保存的路径
@property (nonatomic, assign) BOOL isMaxDuration;// 是否是录音最大时长
@property (nonatomic, assign) BOOL isCurrentTipHIVIP;
@property (nonatomic, strong) HLUserInfoModel *userM;
@property (nonatomic, strong) HLPickerManager *imagePickManager;

@property (nonatomic,   copy) NSString *targetLang; // 对方的语言
@property (nonatomic,   copy) NSString *sourceLang;// 自己的语言
@property (strong,  nonatomic) NSArray *redRewardRecords;
@property (nonatomic, assign) NSInteger cardCount;// 可用的聊天卡数量
@property (nonatomic, copy) NSString *imPrice;
@property (nonatomic, copy) NSString *consumeType; // 聊天扣费类型 0:付费聊天 1:聊天卡 100:免费

@end

@implementation HLMessageSessionViewController


- (void)dealloc
{
    [NIMSDK.sharedSDK.mediaManager stopPlay];
    if ([NIMSDK.sharedSDK.mediaManager isRecording]) {
        [NIMSDK.sharedSDK.mediaManager cancelRecord];
    }
}

- (instancetype)initWithSession:(NIMSession *)session
{
    self = [super initWithSession:session];
    
    if (self) {
        _config = [[HLSessionConfig alloc] initWithSession:session];
        self.title = @"聊天";
        self.enterNormally = YES;
        _isNeedShowFeeTip = YES;
        self.realTransModels = @[
            [HLTransModel modelWithOrigin:@"cn" originAudioLanguage:[IATConfig chinese] object:@"vi" name:@"中转越"],
            [HLTransModel modelWithOrigin:@"cn" originAudioLanguage:[IATConfig chinese] object:@"en" name:@"中转英"],
            [HLTransModel modelWithOrigin:@"vi" originAudioLanguage:[IATConfig vietnamese] object:@"en" name:@"越转英"],
            [HLTransModel modelWithOrigin:@"vi" originAudioLanguage:[IATConfig vietnamese] object:@"cn" name:@"越转中"],
        ];
    }
    
    return self;
}

- (void)viewDidLoad {
    
    if ([HLHelper IMFilterWithSessionId:self.session.sessionId]) {
        self.disableInputView = YES;
    }
    
    self.isCurrentTipHIVIP = YES;
    
    [super viewDidLoad];
    
    self.imagePickManager = [[HLPickerManager alloc] initWithType:HXPhotoManagerSelectedTypePhoto avatar:NO];
    
    HLChatKit.shareSDK.config.inputbarClass = @"HLIMInputBar";
    
    [self setupConfigurator];
    
    [self initRecognizer];
    
    if (![HLHelper IMFilterWithSessionId:self.session.sessionId]) {
        [self requestUserInfo];
    }
    
    self.targetLang = @"zh"; //  默认是zh，有时候会出现获取用户语言失败、或者延迟来到
    // 获取用户的语种
    [GPLangCache.shareInstance fetchLangForKey:self.session.sessionId clientID:self.maleClient completion:^(NSString * _Nonnull lang) {
        self.targetLang = lang;
    }];
    
    if (!([self.session.sessionId isEqualToString:@"1"] || [self.session.sessionId isEqualToString:@"2"] || [self.session.sessionId isEqualToString:@"3"])) {
        [self _requestMaleChatCard];
    }
}

- (void)viewDidDisappear:(BOOL)animated
{
    [super viewDidDisappear:animated];
    [NIMSDK.sharedSDK.mediaManager removeDelegate:self];
}

- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];
    [NIMSDK.sharedSDK.mediaManager addDelegate:self];
}

- (void)userDetail
{
    if (![HLHelper IMFilterWithSessionId:self.session.sessionId]) {
        HLUserDetailViewController *userDetailVC = [[HLUserDetailViewController alloc] initWithUserId:self.session.sessionId];
        [self.navigationController pushViewController:userDetailVC animated:YES];
    }
}

/// 重写父类发送方法，做拦截处理
/// 进行发消息前获取收费情况
- (void)sendMessage:(NIMMessage *)message completion:(void (^)(NSError * _Nonnull))completion
{
    if ([HLRunTime.shareInstance.mine.sex isEqualToString:@"1"]) {
        MJWeakSelf
        [self requestWithCompletion:^(NSString *consumeType, NSError * _Nullable error) {
            if (error) {
                [QMUITips showError:error.localizedDescription];
                if (error.code == 4011) {
                    // 余额不足
                    HLPayRemindAttachment *attachment = [HLPayRemindAttachment.alloc init];
                    attachment.attributedContent = [HLSessionUntils maleNoMoneyTip];
                    
                    NIMMessage *tipMessage = [HLMessageMaker msgWithAttachment:attachment];
                    NIMMessageSetting *setting = tipMessage.setting;
                    setting.shouldBeCounted = NO;
                    setting.historyEnabled = NO;
                    tipMessage.setting = setting;
                    tipMessage.timestamp = [[NSDate date] timeIntervalSince1970];
                    [weakSelf uiInsertMessages:@[tipMessage] callback:^(id  _Nonnull data) {
                    }];
                }
                return;
            }
            
            if ([consumeType isEqualToString:@"100"]) {
                message.remoteExt = [HLSessionUntils removeKey:@"discount" toLocalExt:message.remoteExt];
                message.remoteExt = [HLSessionUntils removeKey:@"isRechargeable" toLocalExt:message.remoteExt];
                message.remoteExt = [HLSessionUntils removeKey:@"type" toLocalExt:message.remoteExt];
                message.localExt = [HLSessionUntils removeKey:@"isUsedCard" toLocalExt:message.localExt];
            } else {
                message.remoteExt = [HLSessionUntils setKeyValue:@{@"discount" : consumeType?:@"0"} toLocalExt:message.remoteExt];
                if ([consumeType isEqualToString:@"1"]) { // 聊天卡
                    message.localExt = [HLSessionUntils setKeyValue:@{@"isUsedCard" : @"1"} toLocalExt:message.localExt];
                }
            }
            
            NSLog(@"[debug] remoteExt = %@", message.remoteExt);
            [super sendMessage:message completion:completion];
            
        } needShowTip:_isNeedShowFeeTip];
    } else {
        message.remoteExt = [HLSessionUntils removeKey:@"discount" toLocalExt:message.remoteExt];
        message.remoteExt = [HLSessionUntils removeKey:@"isRechargeable" toLocalExt:message.remoteExt];
        message.remoteExt = [HLSessionUntils removeKey:@"type" toLocalExt:message.remoteExt];
        message.localExt = [HLSessionUntils removeKey:@"isUsedCard" toLocalExt:message.localExt];
        [super sendMessage:message completion:completion];
    }
}

#pragma mark - <网络>

- (void)requestUserInfo
{
    HLUserInfoRequest *userInfoRequest = [[HLUserInfoRequest alloc] initWithUserId:self.session.sessionId];
    [userInfoRequest startWithCompletionBlockWithSuccess:^(__kindof HLUserInfoRequest * _Nonnull request) {
        if (request.isSuccess){
            self.userM = [request user];
//            [self refreshBackgroundImage:[HLUIHelper avatarPlaceholder] url:self.userM.avatar];
            HLIMKitInputViewImpl *inputView = (HLIMKitInputViewImpl *) self.sessionInputView;
            HLIMInputBar *inputBar = (HLIMInputBar *) inputView.bar;
            [inputBar updatePriceWithVideo:self.userM.videoPrice audio:self.userM.videoPrice];
            self.imTitleView.model = self.userM;
            if (self.userM.userOpuses.count > 0 && ![HLPhotosWallView isHideWithUserId:self.userM.userId]){
                self.photosWallView = [[HLPhotosWallView alloc] init];
                self.photosWallView.userInfor = self.userM;
                [self.view addSubview:self.photosWallView];
                [self.photosWallView mas_makeConstraints:^(MASConstraintMaker *make) {
                    make.left.mas_equalTo(12);
                    make.right.mas_equalTo(-12);
                    make.top.mas_equalTo(NavigationContentTopConstant + 8);
                }];
                [self.interactor changeHeaderHeight:160];
                MJWeakSelf
                [self.photosWallView.closeButton setQmui_tapBlock:^(__kindof UIControl *sender) {
                    [weakSelf.interactor changeHeaderHeight:0];
                    [weakSelf.photosWallView closeAction];
                    [weakSelf.photosWallView removeFromSuperview];
                }];
            }
        } else if ([request.code isEqualToString:@"1003"]){
            [self.navigationController popViewControllerAnimated:YES];
        }
    } failure:nil];
    
}

- (void)_requestMaleChatCard
{
    MJWeakSelf
    [[YMSessionRequest.alloc initWithType:YMSessionRequestTypeAvailableChartCards params:@{@"femaleUserId" : self.session.sessionId?:@""}] startWithCompletionBlockWithSuccess:^(__kindof YMSessionRequest * _Nonnull request) {
        if (request.isSuccess) {
            YMAvailableChartCardsResult *result = request.objectResult;
            weakSelf.cardCount = result.chatCardRemind; //聊天卡数量
            weakSelf.imPrice = result.femaleChatPrice;//聊天收费
            NSString *consumeType = result.consumeType?:@"0";//聊天扣费类型 0:付费聊天 1:聊天卡 100:免费
            
            weakSelf.consumeType = consumeType;
            
            if (result.isChatFee == 0) {
                // 免费提示
                NIMMessage *tipMessage = [HLMessageMaker msgWithTip:@"当前用户免费聊天"];
                NIMMessageSetting *setting = [[NIMMessageSetting alloc] init];
                setting.shouldBeCounted = NO;
                setting.historyEnabled = NO;
                tipMessage.setting = setting;
                tipMessage.timestamp = [[NSDate date] timeIntervalSince1970]+0.5;
                tipMessage.from = HLLoginModel.dataWithKeychain.userId;
                [weakSelf uiInsertMessages:@[tipMessage] callback:^(id  _Nonnull data) {
                }];
            } else {
                // 付费
                if (weakSelf.cardCount > 0) {
                    // 聊天卡提示
                    HLPayRemindAttachment *attachment = [HLPayRemindAttachment.alloc init];
                    attachment.attributedContent = [HLSessionUntils maleChatCardTipWithAvaliableCount:@(self.cardCount).stringValue];
                    
                    NIMMessage *tipMessage = [HLMessageMaker msgWithAttachment:attachment];
                    NIMMessageSetting *setting = tipMessage.setting;
                    setting.shouldBeCounted = NO;
                    setting.historyEnabled = NO;
                    tipMessage.setting = setting;
                    tipMessage.timestamp = [[NSDate date] timeIntervalSince1970];
                    [self uiInsertMessages:@[tipMessage] callback:^(id  _Nonnull data) {
                    }];
                } else {
                    self->_isNeedShowFeeTip = NO;
                    // 收费提示
                    HLPayRemindAttachment *attachment = [HLPayRemindAttachment.alloc init];
                    attachment.attributedContent = [HLSessionUntils attributedTipWithPrice:weakSelf.imPrice];
                    
                    NIMMessage *tipMessage = [HLMessageMaker msgWithAttachment:attachment];
                    NIMMessageSetting *setting = tipMessage.setting;
                    setting.shouldBeCounted = NO;
                    setting.historyEnabled = NO;
                    tipMessage.setting = setting;
                    tipMessage.timestamp = [[NSDate date] timeIntervalSince1970];
                    [weakSelf uiInsertMessages:@[tipMessage] callback:^(id  _Nonnull data) {
                    }];
                }
            }
        }
    } failure:^(__kindof YTKBaseRequest * _Nonnull request) {
        
    }];
}

- (void)requestWithCompletion:(void(^)(NSString * _Nullable consumeType, NSError * _Nullable error))completion needShowTip:(BOOL)showTip;
{
    MJWeakSelf
    // 每次发消息前查询是否可以发消息
    [[YMSessionRequest.alloc initWithType:YMSessionRequestTypeSendAble params:@{@"femaleUserId" : self.session.sessionId?:@""}] startWithCompletionBlockWithSuccess:^(__kindof YMSessionRequest * _Nonnull request) {
        if (request.isSuccess) {
            YMAvailableChartCardsResult *result = request.objectResult;
            NSString *consumeType; // 聊天扣费类型 0:付费聊天 1:聊天卡
            
            if (result.isChatFee == 0) {
                consumeType = @"100";
                self->_isNeedShowFeeTip = YES; // 当变成收费时，需要显示
            } else {
                consumeType = result.consumeType;
            }
            
            completion(consumeType, nil);
            
            if (showTip == NO) {
                return; // 不需要显示提示
            }
            
            if ([consumeType isEqualToString:@"0"]) {
                self->_isNeedShowFeeTip = NO; // 已显示一次收费后，接下来不需要重复显示
                HLPayRemindAttachment *attachment = [HLPayRemindAttachment.alloc init];
                attachment.attributedContent = [HLSessionUntils attributedTipWithPrice:result.femaleChatPrice];
                
                NIMMessage *tipMessage = [HLMessageMaker msgWithAttachment:attachment];
                NIMMessageSetting *setting = tipMessage.setting;
                setting.shouldBeCounted = NO;
                setting.historyEnabled = NO;
                tipMessage.setting = setting;
                tipMessage.timestamp = [[NSDate date] timeIntervalSince1970];
                [weakSelf uiInsertMessages:@[tipMessage] callback:^(id  _Nonnull data) {
                }];
            }
            
            weakSelf.consumeType = consumeType;
        } else {
            completion(nil, [NSError errorWithDomain:@"" code:request.code.integerValue userInfo:@{NSLocalizedDescriptionKey: request.message}]);
        }
    } failure:^(__kindof YMSessionRequest * _Nonnull request) {
        completion(nil, request.error);
    }];
}

- (void)requestToTranToOtherLangText:(NSString *)originText
{
    NSDictionary *params = nil;
    if (self.messageForMenu.isOutgoingMsg) {
        params = @{
            @"body" : originText,
            @"disLang": self.targetLang,
            @"msgId": self.messageForMenu.messageId,
            @"sourceLang" : self.sourceLang
        };
    } else {
        params = @{
            @"body" : originText,
            @"disLang": self.sourceLang,
            @"msgId": self.messageForMenu.messageId,
            @"sourceLang" : self.targetLang
        };
    }
    
    YMTranslacteRequest *transRequest = [YMTranslacteRequest.alloc initWithType:YMTranslacteRequestTypeTranslacte];
    transRequest.params = params;
    [transRequest startWithCompletionBlockWithSuccess:^(__kindof YMTranslacteRequest * _Nonnull request) {
        NSString *text = request.tranlacteResult;
        if (text) {
            self.messageForMenu.text = text;
            [self uiUpdateMessage:self.messageForMenu];
            [NIMSDK.sharedSDK.conversationManager updateMessage:self.messageForMenu forSession:self.session completion:^(NSError * _Nullable error) {
                self.translatingMessage = nil;
                self.iflyResult = nil;
            }];
        } else {
            
        }
    } failure:^(__kindof YTKBaseRequest * _Nonnull request) {
        [QMUITips showError:request.error.localizedDescription];
    }];
}


#pragma mark - <get>

- (NSString *)sourceLang
{
    return HLHelper.language;
}

#pragma mark - <添加网易云信代理>

- (void)addDelegates
{
    [NIMSDK.sharedSDK.chatManager addDelegate:self];
    [NIMSDK.sharedSDK.systemNotificationManager addDelegate:self];
    [NIMSDK.sharedSDK.conversationManager addDelegate:self];
    
    [NSNotificationCenter.defaultCenter addObserver:self selector:@selector(observeDidDeleteAllRemoteMessages:) name:@"IMDidDleteAllRemoteMessages" object:nil];
}

- (void)removeDelegates
{
    [NIMSDK.sharedSDK.chatManager removeDelegate:self];
    [NIMSDK.sharedSDK.systemNotificationManager removeDelegate:self];
    [NIMSDK.sharedSDK.conversationManager removeDelegate:self];
    
    [NSNotificationCenter.defaultCenter removeObserver:self name:@"IMDidDleteAllRemoteMessages" object:nil];
}

- (void)observeDidDeleteAllRemoteMessages:(NSNotification *)notification
{
    NSDictionary *userInfo = [notification userInfo];
    if ([userInfo[@"sessionId"] isEqualToString:self.session.sessionId]) {
        [self uiClearAllMessages];
    }
}

- (void)setupNavigationItems
{
    [super setupNavigationItems];
    
    if (![HLHelper IMFilterWithSessionId:self.session.sessionId]) {
        UIBarButtonItem *moreItem = [[UIBarButtonItem alloc]
                                     initWithImage:UIImageMake(@"imRightIBarItem") style:UIBarButtonItemStylePlain
                                     target:self
                                     action:@selector(clickRightBarItem)];

        self.navigationItem.rightBarButtonItems = @[moreItem];
    }

}

- (NSArray *)menusItems:(NIMMessage *)message
{
    NSMutableArray *items = [NSMutableArray array];
    
    BOOL copyText = NO; // 复制
    BOOL transToLanguage = NO; // 翻译
    BOOL transToText= NO;   // 转文字
    BOOL ear = NO;  // 耳机 扬声器
    BOOL revoke = NO;// 撤回
    BOOL delete = NO; // 删除
    BOOL transToPin = NO; // 音译 转拼音
    BOOL read = NO; // 朗读
    BOOL quote = NO;    // 引用
    BOOL modify = NO; // 改错
    
    if (message.messageType == NIMMessageTypeText)
    {
        copyText = YES;
        transToLanguage = NO;
        transToPin = NO;
        read = YES;
        modify = NO;

        if ([HLHelper getTimeIntervalFromStartTime:message.timestamp toEndTime:[HLHelper currentTimeStamp]] > 2 * 60) {
            delete = YES;
        } else {
            revoke = message.isOutgoingMsg;
        }
    }
    if (message.messageType == NIMMessageTypeAudio) {
        ear = YES;
        if ([HLHelper getTimeIntervalFromStartTime:message.timestamp toEndTime:[HLHelper currentTimeStamp]] > 2 * 60) {
            delete = YES;
        } else {
            revoke = message.isOutgoingMsg;
        }
    }
    
    if (message.messageType == NIMMessageTypeImage || message.messageType == NIMMessageTypeVideo) {
        if ([HLHelper getTimeIntervalFromStartTime:message.timestamp toEndTime:[HLHelper currentTimeStamp]] <= 2 * 60) {
            revoke = message.isOutgoingMsg;
        }
        delete = YES;
    }
    
    if (ear) {
        NSInteger device = [NSUserDefaults.standardUserDefaults integerForKey:@"NIMAudioOutputDevice"];
        NSString *title = nil;
        NSString *image = nil;
        if (device) {
            title = @"听筒";
            image = @"menu_ear";
        } else {
            title = @"扬声器";
            image = @"menu_speaker";
        }
        [items addObject:[HLMenuItem itemWithImage:[UIImage imageNamed:image] title:title target:self action:@selector(switchAudioDevice:)]];
    }
    if (transToLanguage) {
        [items addObject:[HLMenuItem itemWithImage:[UIImage imageNamed:@"menu_fanyi"] title:@"翻译" target:self action:@selector(transToLanguage:)]];
    }
    if (transToPin) {
        [items addObject:[HLMenuItem itemWithImage:[UIImage imageNamed:@"menu_yinyi"] title:@"音译" target:self action:@selector(transToPin)]];
    }
    if (read) {
        [items addObject:[HLMenuItem itemWithImage:[UIImage imageNamed:@"menu_read"] title:@"朗读" target:self action:@selector(speak:)]];
    }
    if (copyText) {
        [items addObject:[HLMenuItem itemWithImage:[UIImage imageNamed:@"menu_copyText"] title:@"复制" target:self action:@selector(copyText:)]];
    }
    if (quote) {
        [items addObject:[HLMenuItem itemWithImage:[UIImage imageNamed:@"menu_quote"] title:@"引用" target:self action:@selector(quote:)]];
    }
    if (transToText) {
        [items addObject:[HLMenuItem itemWithImage:[UIImage imageNamed:@"menu_text"] title:@"转文字" target:self action:@selector(transToText:)]];
    }
    if (revoke) {
        [items addObject:[HLMenuItem itemWithImage:[UIImage imageNamed:@"menu_revoke"] title:@"撤回" target:self action:@selector(revokeMsg:)]];
    }
    
    if (delete) {
        [items addObject:[HLMenuItem itemWithImage:[UIImage imageNamed:@"menu_delete"] title:@"删除" target:self action:@selector(delete:)]];
    }
    if (modify) {
        [items addObject:[HLMenuItem itemWithImage:[UIImage imageNamed:@"menu_modify"] title:@"改错" target:self action:@selector(transToLanguage:)]];
    }
    
    return items;
}

#pragma mark - <事件>

- (void)clickRightBarItem
{
    NSString *blackContent = @"拉黑该用户";
    NSString *blackTitle = @"拉黑";
    BOOL hasBlack = [_userM.isBlacklist boolValue];
    if (hasBlack){
        blackContent = @"将该用户移出黑名单";
        blackTitle = @"移出黑名单";
    }
    
    QMUIAlertAction *actionCancel = [QMUIAlertAction actionWithTitle:@"取消" style:QMUIAlertActionStyleCancel handler:^(QMUIAlertController *aAlertController, QMUIAlertAction *action) {
    }];
    QMUIAlertAction *actionReport = [QMUIAlertAction actionWithTitle:@"举报" style:QMUIAlertActionStyleDefault handler:^(QMUIAlertController *aAlertController, QMUIAlertAction *action) {
        HLReportViewController *reportVC = [[HLReportViewController alloc] initWithType:HLReportTypeMine userId:self.userM.userId];
        [self.navigationController pushViewController:reportVC animated:YES];
    }];
    MJWeakSelf;
    QMUIAlertAction *actionBlack = [QMUIAlertAction actionWithTitle:blackTitle style:QMUIAlertActionStyleDefault handler:^(QMUIAlertController *aAlertController, QMUIAlertAction *action) {
        [HLUIHelper blackWithUserId:weakSelf.userM.userId black:[weakSelf.userM.isBlacklist boolValue] callback:^(BOOL isConfirm) {
            if (isConfirm){
                weakSelf.userM.isBlacklist = hasBlack ? @"0" : @"1";
            }
        }];
    }];

    QMUIAlertController *alertController = [QMUIAlertController alertControllerWithTitle:@"" message:@"" preferredStyle:QMUIAlertControllerStyleActionSheet];
    alertController.sheetButtonAttributes = @{NSForegroundColorAttributeName:HLTextColor1,NSFontAttributeName:UIFontMediumMake(16)};
    alertController.sheetCancelButtonAttributes = @{NSForegroundColorAttributeName:HLTextColor2,NSFontAttributeName:UIFontMediumMake(16)};
    [alertController addAction:actionCancel];
    [alertController addAction:actionReport];
    [alertController addAction:actionBlack];
    [alertController showWithAnimated:YES];
}
/// 唤起底部菜单
/// @param status 0：已关注 1:好友 2:拉黑 null不是好友没有任何关系
- (void)evokeRightBarWithStatus:(NSString * _Nullable)status
{
}

/// 转拼音
- (void)transToPin
{
}

- (void)transToText:(id)sender
{
    [self transToTText:self.messageForMenu needTransLanuage:NO];
}

/// 气泡翻译事件第二部：真正掉翻译接口
- (void)transToLanguage:(id)sender
{
    if (self.messageForMenu.messageType == NIMMessageTypeAudio) {
        [self transToTText:self.messageForMenu needTransLanuage:YES];
    } else {
        NSString *text = self.messageForMenu.text;
        NSString *msg_text_origin_content = self.messageForMenu.remoteExt[@"msg_text_origin_content"];
        if (msg_text_origin_content) {
            text = msg_text_origin_content;
        }
        [self requestToTranToOtherLangText:text];
    }
}

/// 切换音频输出
- (void)switchAudioDevice:(HLMenuItem *)item
{
    NSInteger device = [NSUserDefaults.standardUserDefaults integerForKey:@"NIMAudioOutputDevice"];
    [NIMSDK.sharedSDK.mediaManager switchAudioOutputDevice:1-device];
    [NSUserDefaults.standardUserDefaults setInteger:1-device forKey:@"NIMAudioOutputDevice"];
    [NSUserDefaults.standardUserDefaults synchronize];
    [NIMSDK.sharedSDK.mediaManager setNeedProximityMonitor:NO];
}

/// 菜单删除
- (void)delete:(id)sender
{
    NIMMessage *message = self.messageForMenu;
    
    if (message.deliveryState == NIMMessageDeliveryStateFailed) {
        
        // 未发送成功的消息从本地删除
        
        NIMDeleteMessageOption * opt = [NIMDeleteMessageOption.alloc init];
        opt.removeFromDB = YES;
        [NIMSDK.sharedSDK.conversationManager deleteMessage:message option:opt];
        [self uiDeleteMessage:message];
    } else {
        
        // 已发送成功的消息
        [NIMSDK.sharedSDK.conversationManager deleteMessage:message];
        [self uiDeleteMessage:message];
    }
}

/// 撤回
- (void)revokeMsg:(id)sender
{
    NIMMessage *message = self.messageForMenu;
    MJWeakSelf
    [NIMSDK.sharedSDK.chatManager revokeMessage:message apnsContent:@"你好骚撤回了一条消息" apnsPayload:nil shouldBeCounted:NO completion:^(NSError * _Nullable error) {
        if (error) {
            NSLog(@"error = %@",error);
        } else {
            [weakSelf uiDeleteMessage:message];
            NIMMessage *tipMessage = [HLMessageMaker msgWithTip:@"你撤回了一条消息"];
            if (message.messageType == NIMMessageTypeText) {
                
                NSString *OriginMessage = message.localExt[@"OriginMessage"];
                
                tipMessage.localExt = @{
                    @"TipType" : @"1", // 重新编辑
                    @"OriginMessage" : OriginMessage?:message.text,
                };
            }
            NIMMessageSetting *setting = [[NIMMessageSetting alloc] init];
            setting.shouldBeCounted = NO;
            setting.historyEnabled = YES;
            tipMessage.setting = setting;
            tipMessage.timestamp = [[NSDate date] timeIntervalSince1970];
            [weakSelf uiInsertMessages:@[tipMessage] callback:^(id  _Nonnull data) {
            }];
            
            [[NIMSDK sharedSDK].conversationManager saveMessage:tipMessage
                                                     forSession:self.session
                                                     completion:^(NSError * _Nullable error) {
                if (error) {
                    NSLog(@"error = %@",error);
                }
            }];
        }
    }];
}

/// 引用
- (void)quote:(id)sender
{
    self.quoteMessage = self.messageForMenu;
    self.sessionInputView.status = HLIMInputStatusText;
    [self.sessionInputView quoteMessage:self.messageForMenu];
}

/// 朗读
- (void)speak:(id)sender
{
    HLSpeakerView *speaker = [[HLSpeakerView alloc] init];
    speaker.speakContent = self.messageForMenu.text;
    [speaker show];
}

- (id<HLIMSessionConfig,HLIMKitInputViewConfig>)sessionConfig
{
    return [[HLSessionConfig alloc] initWithSession:self.session];
}

- (void)didFetchMessageData
{
    [super didFetchMessageData];
    [self markRead:self.enterNormally];
    
    /*
     显示地步推荐搭讪话题
     */
    NIMMessage *lastMsg = self.allDatas.lastObject.message;
    
    BOOL flag = !lastMsg;// 没有聊过天
    if (lastMsg.messageType == 100) {
        NIMCustomObject *object = (NIMCustomObject *)self.allDatas.lastObject.message.messageObject;
        flag = flag || [object.attachment isKindOfClass:NSClassFromString(@"HLAccostAttachment")];// 有礼物
    }
    
}

#pragma mark - <添加网易云信代理>

- (void)onRecvMessages:(NSArray<NIMMessage *> *)messages
{
    for (NIMMessage *msg in messages) {
        if ([msg.remoteExt[@"isVideoMessage"] isEqualToString:@"1"]) {
            [self markRead:self.enterNormally];
            return;
        }
        
        if (msg.messageType != 100) {
            [self uiAddMessages:@[msg]];
            // 自动标记已读
            [self markRead:self.enterNormally];
        } else {
            NIMCustomObject *object = (NIMCustomObject *)msg.messageObject;
            if ([object.attachment isKindOfClass:NSClassFromString(@"HLGiftAttachment")]) {
                [self uiAddMessages:@[msg]];
                // 自动标记已读
                [self markRead:self.enterNormally];
            } else if ([object.attachment isKindOfClass:NSClassFromString(@"HLVideoGuideAttachment")]) {
                [self uiAddMessages:@[msg]];
                [self markRead:self.enterNormally];
            } else if ([object.attachment isKindOfClass:NSClassFromString(@"HLVideoGuideAttachment")]) {
                [self uiAddMessages:@[msg]];
                [self markRead:self.enterNormally];
            } else if ([object.attachment isKindOfClass:NSClassFromString(@"HLRechargeAttachment")]) {
               [self uiAddMessages:@[msg]];
               [self markRead:self.enterNormally];
            } else if ([object.attachment isKindOfClass:NSClassFromString(@"HLPayRemindAttachment")]) {
                [self uiAddMessages:@[msg]];
                [self markRead:self.enterNormally];
            } else if ([object.attachment isKindOfClass:NSClassFromString(@"HLOtherRemidAttach")]) {
                [self uiAddMessages:@[msg]];
                [self markRead:self.enterNormally];
                
            } else if ([object.attachment isKindOfClass:NSClassFromString(@"HLAccostAttachment")]) {
                [self uiAddMessages:@[msg]];
                [self markRead:self.enterNormally];
            }
        }
    }
}

/// 监听消息撤回
- (void)onRecvRevokeMessageNotification:(NIMRevokeMessageNotification *)notification
{
    [self uiDeleteMessage:notification.message];
    
    NIMMessage *tipMessage = [HLMessageMaker msgWithTip:[HLSessionUntils tipOnMessageRevoked:notification]];
    NIMMessageSetting *setting = [[NIMMessageSetting alloc] init];
    setting.shouldBeCounted = NO;
    tipMessage.setting = setting;
    tipMessage.timestamp = notification.timestamp;
    [tipMessage setValue:notification.message.messageId forKey:@"messageId"];
    if ([self.session.sessionId isEqualToString:notification.session.sessionId]) {
        [self uiInsertMessages:@[tipMessage] callback:^(id  _Nonnull data) {
        }];
    }
    // saveMessage 方法执行成功后会触发 onRecvMessages: 回调，但是这个回调上来的 NIMMessage 时间为服务器时间，和界面上的时间有一定出入，所以要提前先在界面上插入一个和被删消息的界面时间相符的 Tip, 当触发 onRecvMessages: 回调时，组件判断这条消息已经被插入过了，就会忽略掉。
    [[NIMSDK sharedSDK].conversationManager saveMessage:tipMessage
                                             forSession:notification.session
                                             completion:^(NSError * _Nullable error) {
        if (error) {
            NSLog(@"error = %@",error);
        }
    }];
}

- (void)willSendMessage:(NIMMessage *)message
{
    // 隐藏底部
    [self changeCustomFooterHeight:0];
    
    if ([message.remoteExt[@"isVideoMessage"] isEqualToString:@"1"]) {
        return;
    }
    [super willSendMessage:message];
}

- (void)sendMessage:(NIMMessage *)message didCompleteWithError:(NSError *)error
{
    if ([message.remoteExt[@"isVideoMessage"] isEqualToString:@"1"]) {
        return;
    }
    
    if (!error) {
        if (message.yidunAntiSpamRes.length) {
            message.localExt = [HLSessionUntils setKeyValue:@{@"yidun" : @"1"} toLocalExt:message.localExt];
            // 异步本地存储
            [NIMSDK.sharedSDK.conversationManager updateMessage:message forSession:self.session completion:^(NSError * _Nullable error) {
            }];
            HLPayRemindAttachment *attachment = [HLPayRemindAttachment.alloc init];
            attachment.attributedContent = [NSAttributedString.alloc initWithString:@"内容可能存在违规或引起他人不适" attributes:@{NSFontAttributeName:UIFontMake(12), NSForegroundColorAttributeName:[UIColor qmui_colorWithHexString:@"#FB0037"]}];
            NIMMessage *tipMessage = [HLMessageMaker msgWithCustomObject:attachment];
            tipMessage.from = HLLoginModel.dataWithKeychain.userId;
            [self uiAddMessages:@[tipMessage]];
            
            [[NIMSDK sharedSDK].conversationManager saveMessage:tipMessage
                                                     forSession:self.session
                                                     completion:^(NSError * _Nullable error) {
            }];
        }
        ++_availableSendCount;
        self.enterNormally = YES; // 一旦自己发送消息，立即取消悄悄查看身份，变为正常身份
        [self markRead:YES];
        
//        // 标记这个会话已经回复，可以从收纳的会话列表删除
//        NIMRecentSession *recentSession = [NIMSDK.sharedSDK.conversationManager recentSessionBySession:self.session];
//        if (recentSession.localExt[@"IsReply"] == nil) {
//            [NIMSDK.sharedSDK.conversationManager updateRecentLocalExt:@{@"IsReply" : @"1"} recentSession:recentSession];
//        }
    } else {
        if (error.code == 20003) {
            [QMUITips showError:@"已把对方拉黑"];
        } else if (error.code == 20004) {
            [QMUITips showError:@"对方已把你拉黑"];
        } else {
            [QMUITips showError:error.localizedDescription];
        }
    }
    
    [super sendMessage:message didCompleteWithError:error];
}

- (void)allMessagesClearedInSession:(NIMSession *)session step:(NIMClearMessagesStatus)step
{
    NSLog(@"%s", __FUNCTION__);
    if ([session.sessionId isEqualToString:self.session.sessionId]) {
        // 清空了当前会话
        [self uiClearAllMessages];
    }
}

- (void)messagesDeletedInSession:(NIMSession *)session
{
    NSLog(@"%s", __FUNCTION__);
    if ([session.sessionId isEqualToString:self.session.sessionId]) {
        [self uiClearAllMessages];
    }
}

- (void)onRecvAllRemoteMessagesInSessionDeleted:(NIMSessionDeleteAllRemoteMessagesInfo *)info
{
    NSLog(@"%s", __FUNCTION__);
}

- (void)onReceiveCustomSystemNotification:(NIMCustomSystemNotification *)notification
{
    NSLog(@"%s", __FUNCTION__);
    if (notification.content) {
        NSData *data = [notification.content dataUsingEncoding:NSUTF8StringEncoding];
        NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data
                                                             options:0
                                                               error:nil];
        NSInteger type = 0;
        id object = [dict objectForKey:@"msgType"];
        if ([object isKindOfClass:[NSString class]] ||
            [object isKindOfClass:[NSNumber class]])
        {
            type = [object integerValue];
        }
    }
}

#pragma mark - <输入面板回调>

/// 监听用户点击“发送”按钮的操作
/// - Parameters:
///   - text: 用户编辑的内容
///   - atUsers: 被@的用户们
- (void)onSendText:(NSString *)text atUsers:(NSArray *)atUsers
{
    // 过滤空格
    text = [text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
    // 过滤空内容
    if (text.length == 0) {
        [QMUITips showWithText:@"发送的内容为空"];
        return;
    }
    // 检查是否已完成真人认证
    if (![self checkZhenRen]) {
        return;
    }
    
    // 检查源语言与目标语言一致，若一致不翻译
    if ([self.targetLang isEqualToString:self.sourceLang]) {
        [self _sendText:text needTranslacting:NO];
        return;
    }
    
    BOOL containsChinese = text.containsChinese; // 用户输入的内容是否包含中文
    BOOL containsNonChineseLanguageText = text.containsNonChineseLanguageText; // 用户输入的内容是否包含非中文
    
    // 外文+任意（中文、表情、数字、符号），翻译后发送
    if (containsNonChineseLanguageText) {
        // 翻译
        [self _sendText:text needTranslacting:YES];
        return;
    }

    // 表情+任意（中文、数字、符号）
    if (text.containsEmoticon) {
        // 不翻译 直接发送给对方
        [self _sendText:text needTranslacting:NO];
        return;
    }
    
    // 中文+任意（数字、符号）
    if (containsChinese) {
        // 不翻译 直接发送给对方
        [self _sendText:text needTranslacting:YES];
        return;
    }
    
    // 数字+符号
    // 不翻译 直接发送给对方
    [self _sendText:text needTranslacting:NO];
}

/// 发消息：翻译处理
/// - Parameters:
///   - text: 输入的原文
///   - need: 是否需要翻译后发送
- (void)_sendText:(NSString *)text needTranslacting:(BOOL)need
{
    if (need) {
        // 从自己的语言翻译到对方的语言
        NSDictionary *params = @{
            @"body" : text,
            @"disLang": self.targetLang, // 目标语言，即对方的语言
            @"sourceLang" : self.sourceLang,// 源语言，即自己的语言
            @"toUserId" : self.session.sessionId
        };
        YMTranslacteRequest *transRequest = [YMTranslacteRequest.alloc initWithType:YMTranslacteRequestTypeTranslacte];
        transRequest.params = params;
        [transRequest startWithCompletionBlockWithSuccess:^(__kindof YMTranslacteRequest * _Nonnull request) {
            if (request.tranlacteResult) {
                [self _sendText:request.tranlacteResult originText:text];
            } else {
                [self _sendText:text originText:text];
            }
        } failure:^(__kindof YTKBaseRequest * _Nonnull request) {
            [self _sendText:text originText:text];
        }];
    } else {
        [self _sendText:text originText:text];
    }
}

/// 发消息：发送经过翻译处理的消息
/// - Parameters:
///   - text: 如果需要翻译，此处为翻译后的内容；如果不需要翻译，此处为输入的原文
///   - originText: 输入的原文
- (void)_sendText:(NSString *)text originText:(NSString * _Nullable)originText
{
    NIMMessage *message = nil;
    if ([HLRunTime.shareInstance.mine.sex isEqualToString:@"1"]) {
        message = [HLMessageMaker msgWithText:text discount:self.consumeType?:@"0"];
    } else {
        message = [HLMessageMaker msgWithText:text];
    }
    
    if (originText) {
        // 如果有原文，将原文作为扩展发送给对方，以便对方点击查看原文
        message.localExt = @{@"originContent":originText};
        message.remoteExt = [HLSessionUntils setKeyValue:@{@"msg_text_origin_content":originText,@"isRechargeable":@"1"} toLocalExt:message.remoteExt];
    }

    if (self.quoteMessage) {
        message.remoteExt = [HLSessionUntils setKeyValue:@{
            @"findError" : [@{@"text" : self.quoteMessage.text} mj_JSONString]
        } toLocalExt:message.remoteExt];
    }

    [self sendMessage:message completion:^(NSError * _Nonnull err) {
        if (err) {
            [QMUITips showError:err.localizedDescription];
        }
    }];
    
    [self.sessionInputView clearQuote];
}

- (void)onRecordTouchChanged:(CGPoint)point inView:(UIView *)view state:(UIGestureRecognizerState)state
{

}

- (void)recordBeginTouch
{
    [self private_evokeRecord];
}

- (void)private_evokeRecord
{
    if (NIMSDK.sharedSDK.mediaManager.isRecording) {
        return;
    }
    
    if (@available(iOS 10.0, *)) {
        UIImpactFeedbackGenerator*impactLight = [[UIImpactFeedbackGenerator alloc] initWithStyle:UIImpactFeedbackStyleHeavy];
        [impactLight impactOccurred];
    } else {
        // Fallback on earlier versions
    }
    
    [HLAudioView showRecordingView];
    [NIMSDK.sharedSDK.mediaManager setRecordProgressUpdateTimeInterval:1];
    [NIMSDK.sharedSDK.mediaManager record:NIMAudioTypeAMR duration:60];
}

- (void)recordFinishInButton
{
    // 调用SDK结束录音API
    [HLAudioView dismiss];
    [NIMSDK.sharedSDK.mediaManager stopRecord];
}

- (void)recordDragToOut
{
    // UI显示松开取消的提示
    [HLAudioView showCancelView];
}

- (void)recordDragBackToButton
{
    // 关闭松开取消提示 继续显示录音计时弹窗
    [HLAudioView showRecordingView];
}

- (void)recordFinishOutButton
{
    // 调用SDK取消录音API
    [HLAudioView dismiss];
    [NIMSDK.sharedSDK.mediaManager cancelRecord];
}

- (void)onTapGiftButton:(id)sender
{
    if ([HLRunTime shareInstance].isFood) {
        [QMUITips showWithText:@"对方不在线"];
        return;
    }
    
    MJWeakSelf
    [HLGiftContainerView showWithPlaceType:HLGiftPlaceTypeIM user:_userM callback:^(id gift) {
        if (gift){
            [weakSelf.tableView reloadData];
        }
    }];
}

- (void)onTapVideoCall
{
    if ([HLRunTime shareInstance].isFood) {
        [QMUITips showWithText:@"对方不在线"];
        return;
    }
    
    if (UIScreen.mainScreen.isCaptured) {
        [QMUITips showError:@"录屏期间不可视频"];
        return;
    }
    [HLUIHelper callWithUser:self.userM];
}

- (void)onTapAudioCall
{
    
    if (UIScreen.mainScreen.isCaptured) {
        [QMUITips showError:@"录屏期间不可视频"];
        return;
    }
    
}

- (void)onTapPhotoButton
{
    [self.imagePickManager updateMaxNum:9 photos:nil];
    MJWeakSelf
    [self.imagePickManager showWithController:self block:^(NSArray<HXPhotoModel *> * photos) {
        for (HXPhotoModel *photo in photos) {
            [photo getImageWithSuccess:^(UIImage * _Nullable image, HXPhotoModel * _Nullable model, NSDictionary * _Nullable info) {
                NIMMessage *message = nil;
                if ([HLRunTime.shareInstance.mine.sex isEqualToString:@"1"]) {
                    message = [HLMessageMaker msgWithImage:image discount:self.consumeType];
                } else {
                    message = [HLMessageMaker msgWithImage:image];
                }
                [self sendMessage:message completion:^(NSError * _Nonnull err) {
                    if (err) {
                        NSLog(@"图片发送失败");
                    } else {
                        NSLog(@"图片发送成功");
                    }
                }];
            } failed:nil];
        }
    }];
}

- (void)onTapEmojiButton:(BOOL)isSearch
{
//    MJWeakSelf;
//    [YDEmojiView showWithSearch:isSearch block:^(NSString * emojiUrl, UIImage *image) {
//        NIMMessage *message = [HLMessageMaker msgWithImage:image url:emojiUrl];
//        [weakSelf sendMessage:message completion:^(NSError * _Nonnull err) {
//            if (err) {
//                NSLog(@"图片发送失败");
//            } else {
//                NSLog(@"图片发送成功");
//            }
//        }];
//    }];
}

- (void)onTapEmojiButtonWithUrl:(NSString *)urlString image:(UIImage *)image
{
    NIMMessage *message = [HLMessageMaker msgWithImage:image url:urlString];
    [self sendMessage:message completion:^(NSError * _Nonnull err) {
        if (err) {
            NSLog(@"图片发送失败");
        } else {
            NSLog(@"图片发送成功");
        }
    }];
}

- (void)onTapTopicButton:(UIButton *)btn
{
}

- (BOOL)onStartRealVoice
{
    // 判断VIP类型 再决定要不要使用功能
    self.realVoice = YES;
    [self startListening];
    return YES;
}

- (void)onFinishRealVoice:(void (^)(BOOL))handler
{
    if (self.realVoice) {
        self.realVoice = NO;
        [_iFlySpeechRecognizer stopListening];
        [self.sessionInputView completeRealVoiceTranslaction];
    }
}

- (NSArray *)languagesForRealVoice
{
    return @[@"中转越",@"中转英",@"越转英",@"越转中"];
}

- (void)onSelectedLanguage:(NSInteger)index
{
    // 取消前面的录音
    [NIMSDK.sharedSDK.mediaManager cancelRecord];
    // 选择后重新录音
    NIMSDK.sharedSDK.mediaManager.recordProgressUpdateTimeInterval = 0.05;
    [NIMSDK.sharedSDK.mediaManager record:NIMAudioTypeAMR duration:60];
    self.currentRealVoiceTransIndex = index;
    
    [_iFlySpeechRecognizer setParameter:self.realTransModels[index].originAudioLanguage forKey:[IFlySpeechConstant LANGUAGE]];
}

- (void)onTapCamera
{
    
}

- (void)recordAudio:(NSString *)filePath didBeganWithError:(NSError *)error
{
    if (error) {
        [HLAudioView dismiss];
    }
}

- (void)recordAudioProgress:(NSTimeInterval)currentTime
{
//    CGFloat peakPower = NIMSDK.sharedSDK.mediaManager.recordPeakPower;
//
//    double lowPassResults = pow(10, (0.05 * peakPower));
//
//    [self.sessionInputView changeVoiceValue:lowPassResults];
    
    if (currentTime > 60) {
        self.isMaxDuration = YES;
        // 结束录音
        [NIMSDK.sharedSDK.mediaManager stopRecord];
        UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"" message:@"已经达到最大说话时长，是否发送？" preferredStyle:UIAlertControllerStyleAlert];
        [alert addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
        }]];
        [alert addAction:[UIAlertAction actionWithTitle:@"发送" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
            if (self.audioPath) {
                NIMMessage *message = [HLMessageMaker msgWithAudio:self.audioPath];
                [self sendMessage:message completion:^(NSError * _Nonnull err) {
                    
                }];
            }
        }]];
        [self presentViewController:alert animated:YES completion:nil];
    }
}

- (void)recordAudio:(NSString *)filePath didCompletedWithError:(NSError *)error
{

    [HLAudioView dismiss];
    self.audioPath = filePath;
    // 检测filePath是否有效
    NSURL    *URL = [NSURL fileURLWithPath:filePath];
    
    AVURLAsset *urlAsset = [[AVURLAsset alloc]initWithURL:URL options:nil];
    CMTime time = urlAsset.duration;
    CGFloat mediaLength = CMTimeGetSeconds(time);
    BOOL flag = mediaLength > 2;
    if (flag) {
        if (!self.isMaxDuration) {
            NIMMessage *message = [HLMessageMaker msgWithAudio:filePath];
            [self sendMessage:message completion:^(NSError * _Nonnull err) {
                
            }];
        }
    } else {
        [QMUITips showError:@"说话时间过短"];
    }
}

#pragma mark - <HLIMMessageCellDelegate>

- (void)onRetryMessage:(NIMMessage *)message
{
    
    UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"" message:@"重新发送消息？" preferredStyle:UIAlertControllerStyleAlert];
    [alert addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleDestructive handler:^(UIAlertAction * _Nonnull action) {
        
    }]];
    [alert addAction:[UIAlertAction actionWithTitle:@"重发" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        // 先删除失败的消息
        [self uiDeleteMessage:message];
        NIMDeleteMessageOption * opt = [NIMDeleteMessageOption.alloc init];
        [NIMSDK.sharedSDK.conversationManager deleteMessage:message option:opt];
        
        NIMMessage *msg = nil;
        if (message.messageType == NIMMessageTypeText) {
            msg = [HLMessageMaker msgWithText:message.text];
        } else if (message.messageType == NIMMessageTypeAudio) {
            NIMAudioObject *audioObject = (NIMAudioObject *)message.messageObject;
            msg = [HLMessageMaker msgWithAudio:audioObject.path];
        } else if (message.messageType == NIMMessageTypeVideo) {
            NIMVideoObject *videoObject = (NIMVideoObject *)message.messageObject;
            msg = [HLMessageMaker msgWithAudio:videoObject.path];
        } else if (message.messageType == NIMMessageTypeImage) {
        } else {
            return;
        }
        
         
        [self sendMessage:message completion:^(NSError * _Nonnull err) {
            NSLog(@"重新发送结果 %@", err);
        }];
    }]];
    [self presentViewController:alert animated:YES completion:nil];
}

- (void)onTranslate:(NIMMessage *)message
{
    self.messageForMenu = message;

    // autoExpandFlag 默认是0，当为搭讪消息时，更改为1，且不会再变
    NSString *autoExpandFlag = message.localExt[@"autoExpandFlag"];
    if (autoExpandFlag.length > 0) {
        // 说明是搭讪的消息，从服务端消息扩展取后台翻译的数据，如果没有，走接口翻译
        NSString *tranlaction = message.remoteExt[@"ext"];
        if (tranlaction.length) {
            message.localExt = [HLSessionUntils setKeyValue:@{@"trans" : tranlaction} toLocalExt:message.localExt];
            [self uiUpdateMessage:message];
            [NIMSDK.sharedSDK.conversationManager updateMessage:message forSession:self.session completion:^(NSError * _Nullable error) {
                self.translatingMessage = nil;
                self.iflyResult = nil;
            }];
            return;
        }
    }
    
    // 不再进行翻译，变成显示原文
    if (message.messageType == NIMMessageTypeText) {
        NSString *text = message.text;
        NSString *msg_text_origin_content = message.remoteExt[@"msg_text_origin_content"];
        if (msg_text_origin_content) {
            text = msg_text_origin_content;
        }
        message.localExt = [HLSessionUntils setKeyValue:@{@"trans" : text} toLocalExt:message.localExt];
        [self uiUpdateMessage:message];
        [NIMSDK.sharedSDK.conversationManager updateMessage:message forSession:self.session completion:^(NSError * _Nullable error) {
            self.translatingMessage = nil;
            self.iflyResult = nil;
        }];
    }
}

- (void)onPutaway:(NIMMessage *)message
{
    [self uiUpdateMessage:message];
    [NIMSDK.sharedSDK.conversationManager updateMessage:message forSession:self.session completion:^(NSError * _Nullable error) {
        if (error) {
            [QMUITips showError:error.localizedDescription];
        }
    }];
}

- (BOOL)onTapCell:(HLIMKitEvent *)event
{
    NIMMessage *message = event.messageModel.message;
    if (message.messageType == NIMMessageTypeText) {
        if (!message.isOutgoingMsg) {
            self.messageForMenu = message;
            [self transToLanguage:nil];
        }
    } else if (event.messageModel.message.messageType == NIMMessageTypeTip) {
        NSDictionary *ext = event.messageModel.message.localExt;
        if ([ext[@"TipType"] isEqualToString:@"1"]) {
            [self.sessionInputView insertText:event.data];
        }
    } else if (((event.messageModel.message.messageType == NIMMessageTypeImage) || (event.messageModel.message.messageType == NIMMessageTypeVideo)) && [event.gestureName isEqualToString:HLIMKitGestureTouchUpInside]) {
        NIMMessageSearchOption *opt = [NIMMessageSearchOption.alloc init];
        opt.messageTypes = @[@(NIMMessageTypeImage), @(NIMMessageTypeVideo)];
        opt.limit = 30;
        opt.order = NIMMessageSearchOrderDesc;//取最新
        [NIMSDK.sharedSDK.conversationManager searchMessages:self.session option:opt result:^(NSError * _Nullable error, NSArray<NIMMessage *> * _Nullable messages) {
            
            HXPhotoManager *photoManager = [HXPhotoManager managerWithType:HXPhotoManagerSelectedTypePhotoAndVideo];
            NSInteger index = 0;
            NSMutableArray *models = [NSMutableArray arrayWithCapacity:messages.count];
            for (NIMMessage *msg in messages) {
                if (msg.messageType == NIMMessageTypeImage){
                    NIMImageObject *imgObject = (NIMImageObject *)msg.messageObject;
                    if (imgObject.url.length > 0){
                        HXCustomAssetModel *model = [HXCustomAssetModel assetWithNetworkImageURL:[NSURL URLWithString:imgObject.url] selected:YES];
                        [models addObject:model];
                    }
                    
                } else if (msg.messageType == NIMMessageTypeVideo) {
                    NIMVideoObject *videoObject = (NIMVideoObject *)msg.messageObject;
                    HXCustomAssetModel *model = [HXCustomAssetModel livePhotoAssetWithNetworkImageURL:[NSURL URLWithString:videoObject.coverUrl] networkVideoURL:[NSURL URLWithString:videoObject.url] selected:YES];
                    [models addObject:model];
                }
                if ([msg.messageId isEqualToString:event.messageModel.message.messageId]) {
                    index = [messages indexOfObject:msg];
                }
            }
            if (models.count > 0){
                [photoManager addCustomAssetModel:models];
                [HLPickerManager previewWithManager:photoManager index:index controller:self];
            }
            
            
        }];
    } else if (event.messageModel.message.messageType == NIMMessageTypeRtcCallRecord && [event.gestureName isEqualToString:HLIMKitGestureTouchUpInside]) {
        
        NIMRtcCallRecordObject *record = (NIMRtcCallRecordObject *)event.messageModel.message.messageObject;
        if (record.callType == NIMRtcCallTypeVideo) {
            [self onTapVideoCall];
        } else if (record.callType == NIMRtcCallTypeAudio){
            [self onTapAudioCall];
        }
        
    } else if (event.messageModel.message.messageType == NIMMessageTypeCustom && [event.gestureName isEqualToString:HLIMKitGestureTouchUpInside]) {
        NIMCustomObject *object = (NIMCustomObject *)event.messageModel.message.messageObject;
        if ([object.attachment isKindOfClass:NSClassFromString(@"HLGiftAttachment")]) {
            HLGiftAttachment *attachment = (HLGiftAttachment *)object.attachment;
            HLPreviewGiftView *view = [[HLPreviewGiftView alloc] init];
            [view showGift:attachment onView:self.view];
        } else if ([object.attachment isKindOfClass:NSClassFromString(@"HLPushAttachment")]) {
            HLPushAttachment *attachment = (HLPushAttachment *)object.attachment;
            if ([attachment.pushContentType isEqualToString:@"1"] && attachment.inTurnCode.length > 0) {
                HLUserDetailViewController *vc = [[HLUserDetailViewController alloc] initWithUserId:attachment.inTurnCode];
                [self.navigationController pushViewController:vc animated:YES];
            }
            NSLog(@"attachment %@", attachment);
        } else if ([object.attachment isKindOfClass:NSClassFromString(@"HLVideoGuideAttachment")]) {
            [self onTapVideoCall];
        } else if ([object.attachment isKindOfClass:NSClassFromString(@"HLAccostAttachment")]) {
            HLAccostAttachment *attachment = (HLAccostAttachment *)object.attachment;
            if(attachment.imgUrl.length > 0){
                HLGiftAttachment *gift = [[HLGiftAttachment alloc] init];
                gift.giftImgLink = attachment.imgUrl;
                HLPreviewGiftView *view = [[HLPreviewGiftView alloc] init];
                [view showGift:gift onView:self.view];
            }
        } else if ([object.attachment isKindOfClass:NSClassFromString(@"HLOtherRemidAttach")]) {
            HLOtherRemidAttach *attachment = (HLOtherRemidAttach *)object.attachment;
            if (attachment.msgType == 16) {
                // 去男爵充值页
            } else if (attachment.msgType == 18) {
                // 提示
            } else if (attachment.msgType == 19) {
                // 提示
            } else if (attachment.msgType == 20) {
                // 提示
            } else if (attachment.msgType == 21) {
                // 提示
            } else if (attachment.msgType == 22) {
                // 提示
            } else {
                // 热门话题
                [self onTapTopicButton:[UIButton new]];
            }
        }
    }
    return [super onTapCell:event];
}
- (void)tapEvent
{
    
}

- (BOOL)onTapAvatar:(NIMMessage *)message
{
    if (![HLHelper IMFilterWithSessionId:self.session.sessionId]) {
        //if ([message.from isEqualToString:self.session.sessionId]) {
            HLUserDetailViewController *vc = [[HLUserDetailViewController alloc] initWithUserId:message.from];
            [self.navigationController pushViewController:vc animated:YES];
        //}
    }
    
    return YES;
}

- (BOOL)onLongPressCell:(NIMMessage *)message inView:(UIView *)view
{
    
    BOOL handle = NO;
    NSArray *items = [self menusItems:message];
    if ([items count] ) {
        HLMenuView *menuView = [[HLMenuView alloc] init];
        menuView.items = items;
        [menuView showMenuFromView:view onView:self.view];
        self.messageForMenu = message;
    }
    return handle;
}

- (void)transToTText:(NIMMessage *)message needTransLanuage:(BOOL)needLanguage
{
    if (self.translatingMessage) {
        [QMUITips showError:@"当前有语音消息正在翻译"];
        return;
    }
    
    
    self.translatingMessage = message;
    self.needTransLanguage = needLanguage;
    
    NIMAudioObject *object = (NIMAudioObject *)message.messageObject;
    NIMAudioToTextOption *option = [NIMAudioToTextOption.alloc init];
    option.url = object.url;
    option.filepath = object.path;
    
    if (![NSFileManager.defaultManager fileExistsAtPath:object.path]) {
        [NIMSDK.sharedSDK.resourceManager download:object.url filepath:object.path progress:^(float progress) {
            
        } completion:^(NSError * _Nullable error) {
            NSString *wavPath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject];
            wavPath = [wavPath stringByAppendingString:@"/temp.wav"];
            if ([XKLIMVoiceConverter xklim_convertAmrToWav:object.path wavSavePath:wavPath]) {
                // 设置说话的本国语言
                [self->_iFlySpeechRecognizer setParameter:IATConfig.sharedInstance.language forKey:[IFlySpeechConstant LANGUAGE]];
                [self startListening];
                NSData *audioData = [NSData dataWithContentsOfFile:wavPath];
                [self->_iFlySpeechRecognizer writeAudio:audioData];
                [self->_iFlySpeechRecognizer stopListening];
                NSError *error = nil;
                [NSFileManager.defaultManager removeItemAtPath:wavPath error:&error];
                if (error) {
                    NSLog(@"本地临时翻译音频文件删除失败");
                }
            } else {
                NSLog(@"转换失败");
                self.translatingMessage = nil;
            }
        }];
    } else {
        NSString *wavPath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject];
        wavPath = [wavPath stringByAppendingString:@"/temp.wav"];
        if ([XKLIMVoiceConverter xklim_convertAmrToWav:object.path wavSavePath:wavPath]) {
            // 设置说话的本国语言
            [_iFlySpeechRecognizer setParameter:IATConfig.sharedInstance.language forKey:[IFlySpeechConstant LANGUAGE]];
            [self startListening];
            NSData *audioData = [NSData dataWithContentsOfFile:wavPath];
            [self->_iFlySpeechRecognizer writeAudio:audioData];
            [self->_iFlySpeechRecognizer stopListening];
            NSError *error = nil;
            [NSFileManager.defaultManager removeItemAtPath:wavPath error:&error];
            if (error) {
                NSLog(@"本地临时翻译音频文件删除失败");
            }
        } else {
            NSLog(@"转换失败");
            self.translatingMessage = nil;
        }
    }
}

- (void)rechargeViewPaySuccess
{
    
}

- (BOOL)checkZhenRen
{
    return YES;
}

#pragma mark - 讯飞

-(void)initRecognizer
{

    //recognition singleton without view
    if (_iFlySpeechRecognizer == nil) {
        _iFlySpeechRecognizer = [IFlySpeechRecognizer sharedInstance];
    }

    [_iFlySpeechRecognizer setParameter:@"" forKey:[IFlySpeechConstant PARAMS]];

    //set recognition domain
    [_iFlySpeechRecognizer setParameter:@"iat" forKey:[IFlySpeechConstant IFLY_DOMAIN]];

    _iFlySpeechRecognizer.delegate = self;

    IATConfig *instance = [IATConfig sharedInstance];

    //set timeout of recording
    [_iFlySpeechRecognizer setParameter:instance.speechTimeout forKey:[IFlySpeechConstant SPEECH_TIMEOUT]];
    //set VAD timeout of end of speech(EOS)
    [_iFlySpeechRecognizer setParameter:instance.vadEos forKey:[IFlySpeechConstant VAD_EOS]];
    //set VAD timeout of beginning of speech(BOS)
    [_iFlySpeechRecognizer setParameter:instance.vadBos forKey:[IFlySpeechConstant VAD_BOS]];
    //set network timeout
    [_iFlySpeechRecognizer setParameter:instance.speechTimeout forKey:[IFlySpeechConstant NET_TIMEOUT]];

    //set sample rate, 16K as a recommended option
    [_iFlySpeechRecognizer setParameter:instance.sampleRate forKey:[IFlySpeechConstant SAMPLE_RATE]];

    //set language
    [_iFlySpeechRecognizer setParameter:instance.language forKey:[IFlySpeechConstant LANGUAGE]];
    //set accent
    [_iFlySpeechRecognizer setParameter:instance.accent forKey:[IFlySpeechConstant ACCENT]];

    //set whether or not to show punctuation in recognition results
    [_iFlySpeechRecognizer setParameter:instance.dot forKey:[IFlySpeechConstant ASR_PTT]];
}

- (void)startListening
{
    if (!_iFlySpeechRecognizer) {
        [self initRecognizer];
    }
    
    [_iFlySpeechRecognizer setDelegate:self];
    [_iFlySpeechRecognizer setParameter:@"json" forKey:[IFlySpeechConstant RESULT_TYPE]];
    [_iFlySpeechRecognizer setParameter:IFLY_AUDIO_SOURCE_MIC forKey:@"audio_source"];    //Set audio stream as audio source,which requires the developer import audio data into the recognition control by self through "writeAudio:".
    BOOL ret  = [_iFlySpeechRecognizer startListening];
    
    
    if (ret) {
        //set the category of AVAudioSession
        [IFlyAudioSession initRecordingAudioSession];

        NSLog(@"%s[OUT],Success,Recorder ret=%d",__func__,ret);
    }
    else
    {
       
        NSLog(@"%s[OUT],Failed",__func__);
    }
}

#pragma mark - <讯飞代理>

- (void)onResults:(NSArray *) results isLast:(BOOL)isLast
{
    NSMutableString *resultString = [[NSMutableString alloc] init];
    NSDictionary *dic = results[0];
    
    for (NSString *key in dic) {
        [resultString appendFormat:@"%@",key];
    }
    
    
    NSString * resultFromJson =  nil;
    
    resultFromJson = [ISRDataHelper stringFromJson:resultString];
    
    resultFromJson = [resultFromJson stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
    
    if (self.realVoice) {
        [self.sessionInputView insertText:resultFromJson];
        if (isLast) {
            [self startListening];
        }
    }
}

- (void)onCompleted:(IFlySpeechError *)errorCode
{
    NSLog(@"讯飞识别 error= %@",errorCode);
    if (errorCode.errorCode != 0) {
        if (self.realVoice) {
            self.realVoice = NO;
            return;
        }
        
        self.translatingMessage.localExt = @{
            @"plain" : @"未识别到文字。",
        };
        [self uiUpdateMessage:self.translatingMessage];
        self.translatingMessage = nil;
        self.translatingMessage = nil;
    }
}

- (void) onBeginOfSpeech
{
    NSLog(@"开始录音");
}

- (void) onEndOfSpeech
{
    NSLog(@"结束录音");
}

- (void)onVolumeChanged:(int)volume
{
    [self.sessionInputView changeVoiceValue:volume / 30.f];
}


- (UIImage *)qmui_navigationBarBackgroundImage
{
    return [UIImage qmui_imageWithColor:UIColorWhite];
}

- (nullable UIColor *)qmui_navigationBarTintColor
{
    return UIColorBlack;
}

- (nullable UIColor *)qmui_titleViewTintColor
{
    return UIColorBlack;
}

- (UIStatusBarStyle)preferredStatusBarStyle
{
    return UIStatusBarStyleDarkContent;
}

- (BOOL)preferredNavigationBarHidden
{
    return NO;
}


@end
